package com.sky.Push;

import com.sky.Protocol.MessageChannelHandler;
import com.sky.Protocol.MessageProtocol;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.AdaptiveRecvByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by sun on 2017-06-14.
 */

@Component
@PropertySource("classpath:config.properties")
public class PushServerBootstrap {

    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;

    @Value("${tcp.port}")
    private int port;

    @Value("${tcp.readerIdleTime}")
    private int readerIdleTime;

    @Value("${tcp.scheduleTime}")
    private int scheduleTime;

    public PushServerBootstrap() {
        bossGroup = new NioEventLoopGroup();
        workerGroup = new NioEventLoopGroup();
    }

    private final static Logger logger = LoggerFactory.getLogger(PushServerBootstrap.class);

    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2) ;

    @PostConstruct
    public void init() {

        ExecutorService threadPool =
                Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);

        threadPool.execute( () ->
            {
                try {
                    ServerBootstrap serverBootstrap = new ServerBootstrap();

                    serverBootstrap.option(ChannelOption.SO_BACKLOG,1024)
                            .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
//                            .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator())
                            .childOption(ChannelOption.ALLOCATOR,PooledByteBufAllocator.DEFAULT)
                            .childOption(ChannelOption.TCP_NODELAY,true);

                    serverBootstrap.group(bossGroup,workerGroup)
                            .channel(NioServerSocketChannel.class)
                            .handler(new LoggingHandler(LogLevel.DEBUG))
                            .childHandler(new MessageChannelHandler(readerIdleTime));

                    Channel ch = serverBootstrap.bind(port).sync().channel();

                    logger.info("push server start,port {}",port);

                    ch.closeFuture().sync();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    bossGroup.shutdownGracefully();
                    workerGroup.shutdownGracefully();
                }
            }
        );//threadPool.execute

        scheduledExecutorService.scheduleAtFixedRate(()->{
            ClientManager clientManager = ClientManager.getInstance();
            MessageProtocol msg = new MessageProtocol("ping");
            clientManager.pushAllClient(msg);

            logger.info("------------scheduledExecutorService ping all clients-------------");
        },0,scheduleTime, TimeUnit.SECONDS);

    }
}
